import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import Taro, { useShareAppMessage, useShareTimeline, useTabItemTap, useDidShow } from '@tarojs/taro'
import { View } from '@tarojs/components'
import { useSelector } from 'react-redux'
import dataCenterActions from '@ACTIONS/dataCenter'
import patientActions from '@ACTIONS/patient'
import PainLogSummary from '@COMPONENTS/DataCenter/PainLogSummary'
import DataCenterHeader from '@COMPONENTS/DataCenter/DataCenterHeader'
import CreatePainLog from '@SUBPACKAGES/log/component/CreatePainLog'
import withWebLogin from '@HOC/withWebLogin'
import Scenes, { RouteSceneKey } from '@NAVIGATION/scenes'
import { handleClickTab, showToast, convertPx, getWindowHeight, getPlatform } from '@UTILS/common'
import { Analytic_Type } from '@CONSTANTS/analytic'
import Navigate from '@NAVIGATION/navigateManager'
import shareManage from '@UTILS/shareManage'
import { ROUTER_SCENE_TITLE, SHARE_TYPE } from '@CONSTANTS/app'
import dayjs from 'dayjs'
import { PainLogITF } from '@INTERFACES/PainLog'
import { useRequest } from '@HOOKS/useRequest'
import { CREATE_CLICK_BTN_TYPE, PATIENT_SITE } from '@CONSTANTS/painLog'
import { PatientITF } from '@INTERFACES/Patient'
import api from '@API'
import { GENDER_TYPE } from '@CONSTANTS/common'
import useSetState from '@HOOKS/useSetState'
import debounce from 'lodash.debounce'
import MenstruationDialog from '@COMPONENTS/DataCenter/MenstruationDialog'
import LogGuide from '@COMPONENTS/DataCenter/LogGuide'
import { setGlobalData, getGlobalData } from '@UTILS/globalData'
import style from './DataCenter.module.scss'
const { isWeb } = getPlatform()
interface Props {
  showLogin: () => void
}

const DataCenter: React.FC<Props> = ({ showLogin }) => {
  const language = 'zh'
  const todayBucket = useMemo(() => dayjs().format('YYYY-MM-DD'), [])
  const monthBucket = useMemo(() => dayjs().format('YYYY-MM'), [])
  const dialogForwardRef = useRef<React.MutableRefObject<any>>()
  const [key, setKey] = useState('')
  const [dateBucket, setDateBucket] = useState(todayBucket)
  const [bucket, setBucket] = useState(monthBucket)
  useDidShow(() => {
    const date = getGlobalData('logDateBucket')
    if (date) {
      setDateBucket(date)
      setBucket(date.slice(0, 7))
      setKey(`key:${Math.random()}`)
      setGlobalData('logDateBucket', '')
    }
  })
  const [state, setState] = useSetState({ patientSite: PATIENT_SITE.Head, painLogId: '' })
  const { patientSite, painLogId } = state

  const {
    dispatchGetTodayPainLog, dispatchDeleteLog, dispatchGetPatientMonthPainLog
  } = dataCenterActions
  const {
    dispatchGetMyPatients, dispatchGetPainLogHeadMap, dispatchCreatePainLog, dispatchSetPainLogPatient, dispatchShowCreateLog
  } = patientActions
  const getPainLogHeadMap = useRequest(dispatchGetPainLogHeadMap)
  const getTodayPainLog = useRequest(dispatchGetTodayPainLog)
  const getMyPatients = useRequest(dispatchGetMyPatients)
  const createPainLog = useRequest(dispatchCreatePainLog)
  const setPainLogPatient = useRequest(dispatchSetPainLogPatient)
  const deleteLog = useRequest(dispatchDeleteLog)
  const getPatientMonthPainLogCall = useRequest(dispatchGetPatientMonthPainLog)
  const changeCreateLog = useRequest(dispatchShowCreateLog)

  const getPatientMonthPainLog = useMemo(() => debounce(getPatientMonthPainLogCall, 1000), [getPatientMonthPainLogCall])
  const isVisitor = useSelector(state => state.profile.isVisitor)
  const { user } = useSelector(state => state.profile)
  const { monthPainLogs } = useSelector(state => state.dataCenter)
  const { painLogPatient, myPatients, showCreateLog } = useSelector(state => state.patient)
  const pId = useMemo(() => painLogPatient?.PatientId || painLogPatient?.p8Id || '', [painLogPatient?.PatientId, painLogPatient?.p8Id])
  const fetchData = useCallback(isVisitorLogin => {
    if (isVisitorLogin) return
    getTodayPainLog()
    getPainLogHeadMap()
    getMyPatients()
  }, [getMyPatients, getPainLogHeadMap, getTodayPainLog])

  useTabItemTap(item => {
    const { Gender } = painLogPatient || {}
    const params = { Gender: Gender && GENDER_TYPE[Gender] || '未知' }
    handleClickTab(`/${item.pagePath}`, params)
  })
  const onClickItemTab = useCallback(path => {
    if (path !== Scenes.dataCenter) return
    const isSameMonth = monthBucket === bucket
    const isSameDay = todayBucket === dateBucket
    if (!isSameDay) {
      setDateBucket(todayBucket)
    }
    if (!isSameMonth) {
      setBucket(monthBucket)
    }
    if (!isSameMonth || !isSameDay) {
      setKey(`key:${Math.random()}`)
    }
  }, [bucket, dateBucket, monthBucket, todayBucket])
  useEffect(() => {
    Taro.eventCenter.on('onClickTab', onClickItemTab)
    return () => {
      Taro.eventCenter.off('onClickTab', onClickItemTab)
    }
  }, [onClickItemTab])
  useShareAppMessage(() => {
    Taro.tracker.trackEvent(Analytic_Type.tap_wmp_share.eventId,
      {
        SceneTitle: ROUTER_SCENE_TITLE.dataCenter,
        ShareType: SHARE_TYPE.WeChatFriend
      }, { Scene: RouteSceneKey.dataCenter })
    return shareManage.onShareAppMessage.dataCenter(user)
  })
  useShareTimeline(() => {
    Taro.tracker.trackEvent(Analytic_Type.tap_wmp_share.eventId,
      {
        SceneTitle: ROUTER_SCENE_TITLE.dataCenter,
        ShareType: SHARE_TYPE.WeChatMoment
      }, { Scene: RouteSceneKey.dataCenter })
    return shareManage.onShareTimeline.dataCenter(user)
  })

  const onSelectDate = useCallback(value => {
    const day = dayjs(value).format('YYYY-MM-DD')
    setBucket(value)
    setDateBucket(day)
    setKey(`key:${Math.random()}`)
  }, [])

  const onSelectMenstruationDate = useCallback(async logs => {
    try {
      await api.saveMenstruationLogs({ PatientId: pId, Logs: logs })
      getPatientMonthPainLog(bucket, pId)
      showToast('记录成功')
    } catch (e) {
      showToast(e)
    }
  }, [bucket, getPatientMonthPainLog, pId])
  const onDelete = useCallback((item: PainLogITF) => {
    const { PainLogId } = item
    Taro.tracker.trackEvent(Analytic_Type.num_delete_log.eventId)
    deleteLog(PainLogId, bucket, pId)
  }, [bucket, deleteLog, pId])
  const handlePatient = useCallback(async ({ patients, logPatient, type }) => {
    const hasPatient = Array.isArray(patients) && patients.length > 0
    const onePatient = patients.length === 1
    const painLogPatient = logPatient || patients?.find((item: PatientITF) => item.HasPainLog)
    if (painLogPatient) {
      return true
    }
    if (!hasPatient) {
      showToast('您尚未创建患者，即将为您创建')
      setTimeout(() => {
        Navigate.createLogPatient({ btnType: type })
      }, 800)
      return false
    }
    if (onePatient) {
      try {
        const result = await api.savePatient({
          ...patients[0],
          HasPainLog: true
        })
        setPainLogPatient(result)
        return true
      } catch (e) {
        showToast(e)
      }
    }
    Navigate.selectLogPatient({ btnType: type })
    return false
  }, [setPainLogPatient])
  const loginSuccessMyPatients = useCallback(async () => new Promise<{ patients: PatientITF[]; logPatient: PatientITF }>(resolve => {
    getMyPatients?.({}, (patients: any, logPatient: any) => resolve({ patients, logPatient }))
  }), [getMyPatients])
  const onDayClick = useCallback(({ value }) => {
    setDateBucket(value)
  }, [])

  const onMenstruation = useCallback(async (isVisitorLogin?: boolean) => {
    Taro.tracker.trackEvent(Analytic_Type.num_add_menstruation.eventId)
    const { patients, logPatient } = isVisitorLogin ? await loginSuccessMyPatients() : { patients: myPatients, logPatient: painLogPatient }
    const canContinue = await handlePatient({ patients, logPatient, type: CREATE_CLICK_BTN_TYPE.SAVE_NO_PAIN_LOG })
    if (canContinue) {
      // @ts-ignore
      dialogForwardRef.current?.showDialog?.(bucket)
    }
  }, [bucket, handlePatient, loginSuccessMyPatients, myPatients, painLogPatient])
  const onReport = useCallback(async (isVisitorLogin?: boolean) => {
    Taro.tracker.trackEvent(Analytic_Type.num_add_menstruation.eventId)
    const { patients, logPatient } = isVisitorLogin ? await loginSuccessMyPatients() : { patients: myPatients, logPatient: painLogPatient }
    const canContinue = await handlePatient({ patients, logPatient, type: CREATE_CLICK_BTN_TYPE.SAVE_NO_PAIN_LOG })
    if (canContinue) {
      // @ts-ignore
      Navigate.monthlyReport({ bucket })
    }
  }, [bucket, handlePatient, loginSuccessMyPatients, myPatients, painLogPatient])
  const onClickNoPain = useCallback(async (isVisitorLogin?: boolean) => {
    Taro.tracker.trackEvent(Analytic_Type.num_create_no_pain_log.eventId)
    const { patients, logPatient } = isVisitorLogin ? await loginSuccessMyPatients() : { patients: myPatients, logPatient: painLogPatient }
    const canContinue = await handlePatient({ patients, logPatient, type: CREATE_CLICK_BTN_TYPE.SAVE_NO_PAIN_LOG })
    const currentLogPatient = logPatient || patients?.[0]
    const payLoad = { PatientId: currentLogPatient?.p8Id || currentLogPatient?.PatientId, OverallRating: 0, DateBucket: dateBucket }
    if (canContinue) {
      createPainLog?.(payLoad)
    }
  }, [createPainLog, dateBucket, handlePatient, loginSuccessMyPatients, myPatients, painLogPatient])

  const onEditLog = useCallback(async (item: PainLogITF) => {
    Taro.tracker.trackEvent(Analytic_Type.num_edit_log.eventId)
    setState({
      patientSite: item.HeadPain ? PATIENT_SITE.Head : PATIENT_SITE.Other,
      painLogId: item.PainLogId
    })
    changeCreateLog({ showCreateLog: true })
  }, [setState, changeCreateLog])

  const onCreateLog = useCallback(async (site: PATIENT_SITE, isVisitorLogin?: boolean) => {
    Taro.tracker.trackEvent(site === PATIENT_SITE.Head ? Analytic_Type.num_create_head_log.eventId : Analytic_Type.num_create_body_log.eventId)
    const { patients, logPatient } = isVisitorLogin ? await loginSuccessMyPatients() : { patients: myPatients, logPatient: painLogPatient }
    const canContinue = await handlePatient({ patients, logPatient, type: CREATE_CLICK_BTN_TYPE.SAVE_LOG })
    if (canContinue) {
      setState({
        patientSite: site,
        painLogId: ''
      })
      changeCreateLog({ showCreateLog: true })
    }
  }, [handlePatient, loginSuccessMyPatients, myPatients, painLogPatient, changeCreateLog, setState])
  useEffect(() => {
    fetchData(isVisitor)
  }, [fetchData, isVisitor])
  useEffect(() => {
    if (isVisitor || !pId) return
    getPatientMonthPainLog(bucket, pId)
  }, [bucket, getPatientMonthPainLog, isVisitor, pId])
  const marks = useMemo(() => (isVisitor ? [] : monthPainLogs), [isVisitor, monthPainLogs])
  return (
    <View className={style.dataCenter} style={{ height: `${convertPx(getWindowHeight(isWeb))}` }}>
      <DataCenterHeader
        key={key}
        currentDate={dateBucket}
        maxDate={todayBucket}
        onSelectDate={onSelectDate}
        onDayClick={onDayClick}
        bucket={bucket}
        marks={marks}
        showLogin={showLogin}
        onMenstruation={onMenstruation}
        onReport={onReport}
      />
      <PainLogSummary
        language={language}
        onCreateLog={onCreateLog}
        dateBucket={dateBucket}
        onEditLog={onEditLog}
        onClickNoPain={onClickNoPain}
        onDelete={onDelete}
      />
      { showCreateLog && <CreatePainLog type={patientSite} painLogId={painLogId} dateBucket={dateBucket} />}
      <MenstruationDialog
        forwardRef={dialogForwardRef}
        onSelectDate={onSelectMenstruationDate}
        maxDate={todayBucket}
        monthPainLogs={monthPainLogs}
        pId={pId}
      />
      <LogGuide />
    </View>
  )
}

export default withWebLogin(DataCenter)
